package org.jeese.common.shiro;

import java.util.Set;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.jeese.common.constant.Constant;
import org.jeese.modules.sys.entity.SysUser;
import org.jeese.modules.sys.service.SysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

/**
 * @Description:SHIRO权限认证
 * @Package:org.jeese.security
 * @author:wubc
 * @version:1.0
 * @date:2017年10月30日-下午2:26:36
 * @Copyright:2017 Inc. All rights reserved.
 */
public class ShiroAuthorizingRealm extends AuthorizingRealm {
	protected Logger log = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private SysUserService userService;
	
	public ShiroAuthorizingRealm() {
		//设置凭证匹配器，校验规则
		HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
		credentialsMatcher.setHashAlgorithmName("MD5");
		credentialsMatcher.setHashIterations(2);//两次md5加密
		super.setCredentialsMatcher(credentialsMatcher);
	}
	
    /**
     * 授权(验证权限时调用)
     */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SysUser user = (SysUser) principals.getPrimaryPrincipal();
		// 查到权限数据，返回授权信息(要包括 上边的permissions)
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		// 用户角色
		Set<String> rolesSet = null;
		// 用户权限
		Set<String> permsSet = null;
		if (Constant.SYSTEM_ADMIN.equals(user.getAccount())) {
			rolesSet = userService.getAdminRoles();
			permsSet = userService.getAdminPermsSet();
		} else {
			rolesSet = userService.getUserRoles(user.getUserId());
			permsSet = userService.getUserPermsSet(user.getUserId());
		}
		// 将上边查询到授权信息填充到simpleAuthorizationInfo对象中
		info.addRoles(rolesSet);
		info.addStringPermissions(permsSet);
		return info;
	}

	/**
	 * 认证(登录时调用)
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		log.info("Shiro开始登录认证");
		//得到用户帐号
		String account = (String) token.getPrincipal();
		if(StringUtils.isEmpty(account)){
			throw new UnknownAccountException("账号为空");
		}
		// 查询用户信息
		SysUser user = userService.getByAccount(account);
		// 账号不存在
		if (user == null) {
			throw new UnknownAccountException("用户不存在");
		}
		// 账号锁定
		if (user.getLocked()) {
			throw new LockedAccountException("账号已被锁定,请联系管理员");
		}
		
		// 当验证都通过后，把用户信息放在session里 60分钟过期
		Session session = SecurityUtils.getSubject().getSession();
		session.setTimeout(60 * 60 * 1000);
		session.setAttribute(Constant.SESSION_USER_KEY, user);
		session.setAttribute(Constant.SESSION_USER_ID_KEY, user.getUserId());
		
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getAccount()), getName());
		//SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, password, getName()); 
		return authenticationInfo;
	}
	
	@Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

	
	@Override
	public void onLogout(PrincipalCollection principals) {
		super.clearCachedAuthenticationInfo(principals);
		super.clearCachedAuthorizationInfo(principals);
	}
	
	/**
	 * 清除授权缓存
	 */
	public void clearAllCachedAuthorizationInfo() {  
        getAuthorizationCache().clear();  
    }  
  
    /**
     * 清除认证缓存
     */
    public void clearAllCachedAuthenticationInfo() {  
        getAuthenticationCache().clear();  
    }  
  
    public void clearAllCache() {  
        clearAllCachedAuthenticationInfo();  
        clearAllCachedAuthorizationInfo();  
    }  
	
	/**
	 * 清除当前用户权限缓存
	 */
	public void clearCurrentUserCache(){
		this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
	}
	/**
	 * 清除用户缓存
	 * 
	 * @param loginName
	 */
	public void clearUserCache(String account) {
		if(log.isDebugEnabled()){  
            log.debug("clear the " + account + " authorizationInfo");  
        }  
		SimplePrincipalCollection principals = new SimplePrincipalCollection();
		principals.add(account, super.getName());
		super.clearCachedAuthenticationInfo(principals);
	}
	

}
